package com.ruoyi.system.vo;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;

/**
 * 
 * 
 */
public class Md5Util {

	 private static final String DEFAULT_ENCODING = "UTF-8";

	    public Md5Util() {
	    }
	public final static String MD5(String s) {
        char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
        try {
            byte[] btInput = s.getBytes(Charset.forName("UTF-8"));
            // 获得MD5摘要算法的 MessageDigest 对象
            MessageDigest mdInst = MessageDigest.getInstance("MD5");
            // 使用指定的字节更新摘要
            mdInst.update(btInput);
            // 获得密文
            byte[] md = mdInst.digest();
            // 把密文转换成十六进制的字符串形式
            int j = md.length;
            char str[] = new char[j * 2];
            int k = 0;
            for (int i = 0; i < j; i++) {
                byte byte0 = md[i];
                str[k++] = hexDigits[byte0 >>> 4 & 0xf];
                str[k++] = hexDigits[byte0 & 0xf];
            }
            return new String(str).toUpperCase();
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }


	    public static String MD5(String text, String enocding) {
	        if (text == "" || text == null){
	            return "";
	        }
	        if (enocding == "" || enocding == null){
	            enocding = DEFAULT_ENCODING;
	        }

	        try {
	            byte[] output = MessageDigest.getInstance("MD5").digest(text.getBytes(enocding));
	            StringBuffer out = new StringBuffer();

	            for(int i = 0; i < output.length; ++i) {
	                String t = Integer.toHexString(output[i] & 255);
	                out.append(t.length() == 1 ? "0" + t : t);
	            }
	            return out.toString().toUpperCase();
	        } catch (NoSuchAlgorithmException var6) {
	            var6.printStackTrace();
	        } catch (UnsupportedEncodingException var7) {
	            var7.printStackTrace();
	        }
	        return "";
	    }
	
	    
	    /**
		 * 签名
		 * @param SortedMap
		 * @param md5Key 注意md5key各家不同
		 * @return
		 */
		public static String signData(Map<String, String> SortedMap, String md5Key) {
			List<String> stringSort = new ArrayList<String>();

			for (java.util.Map.Entry<String, String> entry : SortedMap.entrySet()) {
				if (entry.getValue() != null && !"".equals(entry.getValue())
						&& !"null".equals(entry.getValue()) && !entry.getKey().equals("sign") && !entry.getKey().equals("pl_sign") ) {
					stringSort.add(entry.getKey());
				//	logger.debug("========"+  entry.getKey()+"========["+entry.getValue()+"]");
				}
			}
			Collections.sort(stringSort, Collator.getInstance(Locale.CHINA));//排序
			StringBuffer signDatas = new StringBuffer();
			for (int i = 0; i < stringSort.size(); i++) {
				signDatas.append(SortedMap.get(stringSort.get(i)));
			}
			signDatas.append(md5Key);
			String sign = encrypt2MD5(signDatas.toString());
			return sign;
		}

		public static String encrypt2MD5(String originstr) {
			String result = null;
			// 用来将字节转换成 16 进制表示的字符
			char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
					'a', 'b', 'c', 'd', 'e', 'f' };
			if (originstr != null && !"".equals(originstr)) {
				try {
					// 返回实现指定摘要算法的 MessageDigest 对象
					MessageDigest md = MessageDigest.getInstance("MD5");
					// 使用utf-8编码将originstr字符串编码并保存到source字节数组
					byte[] source = originstr.getBytes("utf-8");
					// 使用指定的 byte 数组更新摘要
					md.update(source);
					// 通过执行诸如填充之类的最终操作完成哈希计算,结果是一个128位的长整数
					byte[] tmp = md.digest();
					// 用16进制数表示需要32位
					char[] str = new char[32];
					for (int i = 0, j = 0; i < 16; i++) {
						// j表示转换结果中对应的字符位置
						// 从第一个字节开始,对 MD5 的每一个字节
						// 转换成 16 进制字符
						byte b = tmp[i];

						// 取字节中高 4 位的数字转换
						// 无符号右移运算符>>> ,它总是在左边补0
						// 0x代表它后面的是十六进制的数字. f转换成十进制就是15
						str[j++] = hexDigits[b >>> 4 & 0xf];

						// 取字节中低 4 位的数字转换
						str[j++] = hexDigits[b & 0xf];
					}

					// 结果转换成字符串用于返回
					result = new String(str);

				} catch (NoSuchAlgorithmException e) {
					e.printStackTrace();
				} catch (UnsupportedEncodingException e) {
					e.printStackTrace();
				}

			}

			return result;
		}
		
		public static String signDatabc(Map<String, String> SortedMap, String md5Key) {
			List<String> stringSort = new ArrayList<String>();

			for (java.util.Map.Entry<String, String> entry : SortedMap.entrySet()) {
				if (entry.getValue() != null && !"".equals(entry.getValue())
						&& !"null".equals(entry.getValue()) && !entry.getKey().equals("sign") && !entry.getKey().equals("pl_sign") ) {
					stringSort.add(entry.getKey());
				//	logger.debug("========"+  entry.getKey()+"========["+entry.getValue()+"]");
				}
			}
			Collections.sort(stringSort, Collator.getInstance(Locale.CHINA));//排序
			StringBuffer signDatas = new StringBuffer();
			for (int i = 0; i < stringSort.size(); i++) {
					signDatas.append(stringSort.get(i)).append("=").append(SortedMap.get(stringSort.get(i))).append("&");
			}
			String s = signDatas.substring(0, signDatas.length()-1);
			String ss = s+md5Key;
			System.out.println("加密测试的测试参数为"+ss);
			return MD5Encode(ss);
		}


		
		
		public static String getKeyedDigest(String strSrc, String key) {
	        try {
	            MessageDigest md5 = MessageDigest.getInstance("MD5");
	            md5.update(strSrc.getBytes(Common.CHARSET));
	            
	            String result="";
	            byte[] temp;
	            temp=md5.digest(key.getBytes(Common.CHARSET));
	            for (int i=0; i<temp.length; i++){
	                result+=Integer.toHexString((0x000000ff & temp[i]) | 0xffffff00).substring(6);
	            }
	            
	            return result;
	            
	        } catch (NoSuchAlgorithmException e) {
	            
	            e.printStackTrace();
	            
	        }catch(Exception e)
	        {
	          e.printStackTrace();
	        }
	        return null;
	    }
	    
	    public static String getSignParam(Map<String,String> params){
	        StringBuilder buf = new StringBuilder((params.size() +1) * 10);
	        buildPayParams(buf,params,false);
	        String result = buf.toString();    
	        return result;
	    }
	    
	    /**
	     * @author 
	     * @param payParams
	     * @return
	     */
	    public static void buildPayParams(StringBuilder sb,Map<String, String> payParams,boolean encoding){
	        List<String> keys = new ArrayList<String>(payParams.keySet());
	        Collections.sort(keys);
	        for(String key : keys){
	            sb.append(key).append("=");
	            if(encoding){
	                sb.append(urlEncode(payParams.get(key)));
	            }else{
	                sb.append(payParams.get(key));
	            }
	            sb.append("&");
	        }
	        sb.setLength(sb.length() - 1);
	    }
	    
	    public static String urlEncode(String str){
	        try {
	            return URLEncoder.encode(str, "UTF-8");
	        } catch (Throwable e) {
	            return str;
	        } 
	    }

	    /**
	     * 将指定的字符串用MD5加密 originstr 需要加密的字符串
	     * 
	     * @param originstr
	     * @return
	     */

	    public static String ecodeByMD5(String originstr)
	    {

	        String result = null;

	        char hexDigits[] =
	        {// 用来将字节转换成 16 进制表示的字符

	        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };

	        if (originstr != null)
	        {

	            try
	            {

	                // 返回实现指定摘要算法的 MessageDigest 对象

	                MessageDigest md = MessageDigest.getInstance("MD5");

	                // 使用utf-8编码将originstr字符串编码并保存到source字节数组

	                byte[] source = originstr.getBytes("utf-8");

	                // 使用指定的 byte 数组更新摘要

	                md.update(source);

	                // 通过执行诸如填充之类的最终操作完成哈希计算，结果是一个128位的长整数

	                byte[] tmp = md.digest();

	                // 用16进制数表示需要32位

	                char[] str = new char[32];

	                for (int i = 0, j = 0; i < 16; i++)
	                {

	                    // j表示转换结果中对应的字符位置

	                    // 从第一个字节开始，对 MD5 的每一个字节

	                    // 转换成 16 进制字符

	                    byte b = tmp[i];

	                    // 取字节中高 4 位的数字转换

	                    // 无符号右移运算符>>> ，它总是在左边补0

	                    // 0x代表它后面的是十六进制的数字. f转换成十进制就是15

	                    str[j++] = hexDigits[b >>> 4 & 0xf];

	                    // 取字节中低 4 位的数字转换

	                    str[j++] = hexDigits[b & 0xf];

	                }

	                result = new String(str);// 结果转换成字符串用于返回

	            }
	            catch (NoSuchAlgorithmException e)
	            {
	                e.printStackTrace();
	            }
	            catch (UnsupportedEncodingException e)
	            {
	                e.printStackTrace();
	            }
	        }

	        return result;
	    }

	    /**
	     * 创建密匙
	     * 
	     * @param algorithm
	     *            加密算法,可用 DES,DESede,Blowfish
	     * @return SecretKey 秘密（对称）密钥
	     */
	    public static SecretKey createSecretKey(String algorithm)
	    {
	        // 声明KeyGenerator对象
	        KeyGenerator keygen;
	        // 声明 密钥对象
	        SecretKey deskey = null;
	        try
	        {
	            // 返回生成指定算法的秘密密钥的 KeyGenerator 对象
	            keygen = KeyGenerator.getInstance(algorithm);
	            // 生成一个密钥
	            deskey = keygen.generateKey();
	        }
	        catch (NoSuchAlgorithmException e)
	        {
	            e.printStackTrace();
	        }
	        // 返回密匙
	        return deskey;
	    }

	    

	    private static final String[] hex = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };

	    public static String Encode(String password) {
	        try {
	            MessageDigest md5 = MessageDigest.getInstance("MD5");
	            byte[] byteArray = md5.digest(password.getBytes("utf-8"));
	            String passwordMD5 = byteArrayToHexString(byteArray);
	            return passwordMD5;
	        } catch (Exception e) {
	            e.fillInStackTrace();
	        }
	        return password;
	    }
	    
	    public static String MD5Encode(String origin, String charsetname) {
			String resultString = null;
			try {
				resultString = new String(origin);
				MessageDigest md = MessageDigest.getInstance("MD5");
				if (charsetname == null || "".equals(charsetname))
					resultString = byteArrayToHexString(md.digest(resultString.getBytes()));
				else
					resultString = byteArrayToHexString(md.digest(resultString.getBytes(charsetname)));
			} catch (Exception exception) {
			}
			return resultString;
		}



	    private static String byteArrayToHexString(byte[] byteArray) {
	        StringBuffer sb = new StringBuffer();
	        for (byte b : byteArray) {
	            sb.append(byteToHexChar(b));
	        }
	        return sb.toString();
	    }

	    private static Object byteToHexChar(byte b) {
	        int n = b;
	        if (n < 0) {
	            n = 256 + n;
	        }
	        int d1 = n / 16;
	        int d2 = n % 16;
	        return hex[d1] + hex[d2];
	    }
	    /**
		 * MD5编码
		 * 
		 * @param origin
		 *            原始字符串
		 * @return 经过MD5加密之后的结果
		 */
		public static String MD5Encode(String origin) {
			String resultString = null;
			try {
				resultString = origin;
				MessageDigest md = MessageDigest.getInstance("MD5");
				resultString = byteArrayToHexString(md.digest(resultString.getBytes()));
			} catch (Exception e) {
				e.printStackTrace();
			}
			return resultString;
		}
		
		
}
